package com.example.yanke.printerc1;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.szsicod.print.escpos.PrinterAPI;
import com.szsicod.print.io.InterfaceAPI;
import com.szsicod.print.io.USBAPI;
import com.szsicod.print.io.UsbNativeAPI;
import java.util.concurrent.ArrayBlockingQueue;


/**
 * Created By kzz on 2021/8/17
 * Describe:
 */
public class YKPrinterC1Manager {

    private Context mContext;
    private PrinterAPI mPrinter;
    private UsbBroadCastReceiver mUsbBroadCastReceiver;
    private String TAG = "YKPrinterC1Manager";
    private final int INIT_ERROR = 1;
    private MyHandler mHandler;
    private static YKPrinterC1Manager instance = null;
    private ConnectThread mConnectThread;
    private ArrayBlockingQueue<YKPrinterC1Listener> mListenerQueue;

    private YKPrinterC1Manager(Context context) {
        this.mContext = context;
        mPrinter = PrinterAPI.getInstance();
        mHandler = new MyHandler();
        mListenerQueue = new ArrayBlockingQueue<>(100);
        mConnectThread = new ConnectThread();
        mConnectThread.start();
    }

    public static YKPrinterC1Manager getInstance(Context context) {
        if (instance == null) {
            synchronized (YKPrinterC1Manager.class) {
                if (instance == null) {
                    instance = new YKPrinterC1Manager(context);
                }
            }
        }
        return instance;
    }

    public void initPrinter(YKPrinterC1Listener mYKPrinterC1Listener) {
        mListenerQueue.offer(mYKPrinterC1Listener);
    }

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case INIT_ERROR://打印异常
                    try {
                        mListenerQueue.take().initError((String) msg.obj);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    break;
            }
        }
    }

    //usb 监听 由于权限问题而且sdk内部有超时时间 ,适用情况应该是系统默认usb权限开放或者root 板则使用UsbNativeApi
    private class UsbBroadCastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d(TAG, action);
            if (!TextUtils.isEmpty(action))
                if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
                    UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (usbDevice != null) {
                        InterfaceAPI io = PrinterAPI.getInstance().getIO();
                        if (io instanceof USBAPI || io instanceof UsbNativeAPI) {
                            PrinterAPI.getInstance().disconnect();
                            Log.d(TAG, "打印机断开连接");
                        }
                    }
                } else if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                    if (PrinterAPI.getInstance().isConnect()) return;
                    Runnable runnable = new Runnable() {
                        @Override
                        public void run() {

                            USBAPI usbapi = new USBAPI(mContext);
                            String mess = "";
                            if (PrinterAPI.getInstance().connect(usbapi) == PrinterAPI.SUCCESS) {
                                mess = "打印机连接成功";
                            } else {
                                mess = "打印机连接失败";
                            }
                            Log.d(TAG, mess);
                        }
                    };
                    new Thread(runnable).start();

                }

        }
    }

    private class ConnectThread extends Thread {

        boolean isInterrupt;

        @Override
        public void run() {
            while (!isInterrupt) {
                try {
                    if (mUsbBroadCastReceiver == null) {
                        IntentFilter intentFilter = new IntentFilter();
                        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
                        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
                        mUsbBroadCastReceiver = new UsbBroadCastReceiver();
                        mContext.registerReceiver(mUsbBroadCastReceiver, intentFilter);
                    }
                    InterfaceAPI io = new USBAPI(mContext);

                    if (PrinterAPI.SUCCESS == mPrinter.connect(io)) {
                        //连接设备成功
//                        handler.sendMessage(handler.obtainMessage(INIT_SUCCESS));
                        mListenerQueue.take().initSuccess(mPrinter);

                    } else {
                        //连接设备失败
                        mHandler.sendMessage(mHandler.obtainMessage(INIT_ERROR, "打印机连接失败"));
                        isInterrupt=true;
                        sleep(1500);
                        releasePrint();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void interrupt() {
            isInterrupt = true;
            super.interrupt();
        }
    }

    /**
     * 释放资源(打印中不要调用此方法，不然打印会停止)
     */
    public void releasePrint() {
        if (mHandler != null)
            mHandler.removeCallbacksAndMessages(null);
        if (mPrinter != null) {
            mPrinter.disconnect();
            mPrinter = null;
            Log.d(TAG, "打印机资源已经关闭");
        }
        if (mUsbBroadCastReceiver != null && mContext != null)
            mContext.unregisterReceiver(mUsbBroadCastReceiver);
        instance = null;
        if (mConnectThread!=null) {
            mConnectThread.isInterrupt = true;
            mConnectThread.interrupt();
        }
    }
}
